<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>Document</title>
</head>
<body>
	<script type="text/javascript">
		// 1、函数自然执行时，this指向全局对象或者 undefined(严格模式)
		function logThis(){
			console.log(this)
		}
		function outer(){
			logThis()
		}
		// 无论嵌套多少层，只要函数是自然执行，那么就指向全局对象
		outer()

		// 2、执行时，谁点出来就是谁
		var name = 'window'
		var teacher = {
			name: 'teacher',
			buy: function(){
				console.log(this.name)
			},
			wife:{
				name: 'wife',
				buy:function(){
					console.log(this.name)
				}
			}
		}
		var woman = {
			name: 'woman'
		}
		woman.buy = teacher.buy
		var buy = woman.buy
		buy() // window
		woman.buy() // woman
		teacher.buy() // teacher
		teacher.wife.buy(); // wife
		// 逗号表达式，返回最后一个值
		(1, teacher.buy)(); // window
		// 3、 new执行时，指向的是 new 出来的那个对象
		function Person(){
			console.log(this)
		}
		var student = new Person() // 这里 this 指向 student 而不是 Person

		// 4、 call、apply、bind

		// call和apply会立即执行


		// bind，不会立即执行，也不会改变原函数
		function bindFn(first, second) {
			console.log('this:::', this, first, second, this.name)
		}
		var car = {
			name: 'bmw'
		}
		var wife = {
			name: 'wife'
		}
		var carFunc = bindFn.bind(car,1, 2)
		wife.bindFn = carFunc
		// wife.bindFn()

		// 箭头函数  this 指向声明箭头函数的没有被箭头函数包裹的执行上下文
		// 定义时，离箭头函数最近的上下文的 this 指向哪里，则箭头函数的 this 就指向哪里
		// 箭头函数不受 call apply bind的影响
		// call和apply执行绑定、修改箭头函数this时，不会生效也不会报错
		var personObj = {
			name: 'sam',
			showName: function(){
				var showThis = () => {
					console.log('对象内部的箭头函数this:::', this)
				}
				showThis()
			}
		}
		// personObj.showName() // personObj
		function outerFn(){
			console.log("outerFn上下文this:::", this)
			// 这里的箭头函数 buy 的 this指向取决于 函数 outerFn 上下文的this指向
			const buy = () => {
				console.log('箭头函数this:::', this)
			}
			buy()
		}
		// 赋值给对象属性调用时outerFn this指向对象 personObj,所以,箭头函数也指向对象personObj
		personObj.outerFn = outerFn
		personObj.outerFn() 
		outerFn() // 单独调用时，outerFn this 指向 window所以 内部的箭头函数this也指向 window

		const buyFn = () => {
			console.log('没有被包裹的箭头函数this:::',this)
		}
		// buyFn() // window


		// 执行上下文最明显的就是 this 的指向是执行时确定的。而作用域访问的变量是编写代码的结构确定的。


		
	</script>
</body>
</html>